/*
	This file is part of AVRCppLib.

    AVRCppLib is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    AVRCppLib is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with AVRCppLib.  If not, see <http://www.gnu.org/licenses/>.

    Copyright (C) Maxime Lemonnier 2007-2011
 */

#ifndef FT245HARDWARE_H_
#define FT245HARDWARE_H_

#include "Utils/CppExtensions.h"
#include <avr/delay.h>


class FT245Hardware {
protected:
	IOAddress dataPort, dataDDR, dataPin;
	IOAddress controlPort, controlDDR, controlPin;
	uint8_t txe;
	uint8_t rxf;
	uint8_t wr;
	uint8_t rd;
	uint8_t pwren;

	inline void setOuputMode() FORCE_INLINE
	{
		*dataPort = 0x00; //disable pull-up resistors
		*dataDDR = 0xFF;  //output
	}

	inline void setInputMode() FORCE_INLINE
	{
		*dataPort = 0x00;
		*dataDDR = 0x00; //input
		*dataPort = 0xFF; //enable pull-up resistors
	}

public:
	FT245Hardware(IOAddress dataPort, IOAddress dataDDR, IOAddress dataPin,
			IOAddress controlPort, IOAddress controlDDR,IOAddress controlPin,
			uint8_t txe, uint8_t rxf, uint8_t wr, uint8_t rd, uint8_t pwren) :
		dataPort(dataPort), dataDDR(dataDDR), dataPin(dataPin),
		controlPort(controlPort), controlDDR(controlDDR), controlPin(controlPin),
		txe(txe), rxf(rxf), wr(wr), rd(rd), pwren(pwren)
	{
		set2Bits(*controlDDR, wr, rd);
		clear3Bits(*controlDDR, rxf, txe, pwren);
		set3Bits(*controlPort, rxf, txe, pwren);

		setOuputMode();
	}
//#define USBreadAllowed()	(CONTROL_PIN & RXF) != RXF
//#define USBwriteAllowed()  	(CONTROL_PIN & TXE) != TXE
//#define USBConfigured() 	(CONTROL_PIN & PWREN) != PWREN
	inline void writeByte(uint8_t byte) FORCE_INLINE
	{
		setOuputMode();
		while(bitIsSetInRegister(*controlPin, txe));

		*dataPort = byte;
		clearBit(*controlPort, wr);
		_delay_us(.1);
		setBit(*controlPort, wr);
	}

	inline uint8_t readByte() FORCE_INLINE
	{
		uint8_t byte = 0x00;
		setInputMode();
		while(bitIsSetInRegister(*controlPin, rxf));

		clearBit(*controlPort, rd);
		_delay_us(.1);
		byte = *dataPin;
		setBit(*controlPort, rd);

		return byte;
	}

	virtual ~FT245Hardware();
};

#endif /* FT245HARDWARE_H_ */
